#include "Ship.h"
#include <string>
#include "../../common/lib/SDL_rotozoom.h"

Ship::Ship(ShipStatus* shipStatus) :
		WidgetMovimiento(shipStatus->getPosX(), shipStatus->getPosY(),shipStatus->getImagePath(), parent) {

	//Informacion basica
	imagePath = shipStatus->getImagePath();
	this->rotationVelocity = shipStatus->getVelRotacion();
	this->maximumVelocity = shipStatus->getVelMax();
	this->propulsion = shipStatus->getPropultion();
	this->friction = shipStatus->getFriccion();
	this->bulletDuration = shipStatus->getDuracionBala();

	std::stringstream ss;
	ss << "owner: " << owner;
	//	Logger::log("Ship", "constructor", &ss);

	this->owner = owner;

	shipSurface = SurfaceUtils::loadImage(SH_DEFAULT_IMAGE);

	combustionShipSurface = SurfaceUtils::loadImage(SH_DEFAULT_IMAGE_COMBUSTION);

	//Setting transparent image color
	SDL_SetColorKey(shipSurface, SDL_SRCCOLORKEY,
			SDL_MapRGB(shipSurface->format, 0, 255, 255));

	//Setting transparent image color
	SDL_SetColorKey(combustionShipSurface, SDL_SRCCOLORKEY,
			SDL_MapRGB(combustionShipSurface->format, 0, 255, 255));

	surface = shipSurface;

	parcel = getPosition();
	parcel.height = surface->h;
	parcel.width = surface->w;
	nextX = parcel.posX;
	nextY = parcel.posY;

	this->angle = angle;

	goingBackwards = false;
	goingForward = false;
	turningLeft = false;
	turningRight = false;
	shooting = false;
	this->angle = angle;
	keyPressed = false;
	velocity = 0;
	angle0 = angle;
	combustion = false;
}

Ship::Ship(std::string pathImage, float rotationVelocity, int maximumVelocity,
		int propultion, int friccion, int duracionBala, int posX, int posY,
		Widget *parent, std::string owner, int angle) :
		WidgetMovimiento(posX, posY,pathImage, parent) {

	//Informacion basica
	this->imagePath = pathImage;
	this->rotationVelocity = rotationVelocity;
	this->maximumVelocity = maximumVelocity;
	this->propulsion = propultion;
	this->friction = friccion;
	this->bulletDuration = duracionBala;

	std::stringstream ss;
	ss << "owner: " << owner;
	//	Logger::log("Ship", "constructor", &ss);

	this->owner = owner;

	shipSurface = SurfaceUtils::loadImage(pathImage);
	if (shipSurface == NULL) {
		shipSurface = SurfaceUtils::loadImage(SH_DEFAULT_IMAGE);
	}

	//Retrieving combustion image file path
	std::string pathCombustionImage = pathImage.substr(0,pathImage.rfind('.'));
	std::string extension = pathImage.substr(pathImage.rfind('.')); ;
	pathCombustionImage.append("_fuego" + extension);
	combustionShipSurface = SurfaceUtils::loadImage(pathCombustionImage);
	if (combustionShipSurface == NULL) {
		combustionShipSurface = SurfaceUtils::loadImage(SH_DEFAULT_IMAGE_COMBUSTION);
	}

	//Setting transparent image color
	SDL_SetColorKey(shipSurface, SDL_SRCCOLORKEY,
			SDL_MapRGB(shipSurface->format, 0, 255, 255));

	//Setting transparent image color
	SDL_SetColorKey(combustionShipSurface, SDL_SRCCOLORKEY,
			SDL_MapRGB(combustionShipSurface->format, 0, 255, 255));

	surface = shipSurface;

	parcel = getPosition();
	parcel.height = surface->h;
	parcel.width = surface->w;

	nextX = parcel.posX;
	nextY = parcel.posY;
	this->angle = angle;

	goingBackwards = false;
	goingForward = false;
	turningLeft = false;
	turningRight = false;
	shooting = false;
	this->angle = angle;
	keyPressed = false;
	velocity = 0;
	angle0 = angle;
	combustion = false;
}

void Ship::handleEvent(Event event) {
	/*std::stringstream owner;
	 owner << "owner: " << this->owner;

	 Logger::log("Ship", "handleEvent", &owner);*/

	if ((event.getSender() == this->owner) || duenoesinstancialocal) {

		if (event.getType() == UserEvent) {

			Logger::log("Ship", "handleEvent", "entro al handle del ship");

			if (event.getintData2() == KeyDown) {
				if (event.getEvent()->user.code == KeyPressed) {
					goingBackwards = true;
				} else if (event.getEvent()->user.code == KeyReleased) {
					goingBackwards = false;
				}
			}

			else if (event.getintData2() == KeyUp) {
				if (event.getEvent()->user.code == KeyPressed) {
					Logger::log("Ship", "handleEvent", "toma el evento");
					goingForward = true;
				} else if (event.getEvent()->user.code == KeyReleased) {
					goingForward = false;
				}
			}

			else if (event.getintData2() == KeyLeft) {
				if (event.getEvent()->user.code == KeyPressed) {
					turningLeft = true;
				} else if (event.getEvent()->user.code == KeyReleased) {
					turningLeft = false;
				}
			}

			else if (event.getintData2() == KeyRight) {
				if (event.getEvent()->user.code == KeyPressed) {
					turningRight = true;
				} else if (event.getEvent()->user.code == KeyReleased) {
					turningRight = false;
				}
			}

			else if (event.getintData2() == Space) {
				if (event.getEvent()->user.code == KeyPressed) {
					shooting = true;
				} else if (event.getEvent()->user.code == KeyReleased) {
					shooting = false;
				}
			}
		} else {

			//	keyState = event.getType();
			switch (event.getKey()) {
			case KeyDown:
				if (event.getType() == KeyPressed) {
					goingBackwards = true;
				} else if (event.getType() == KeyReleased) {
					goingBackwards = false;
				}
				keyPressed = false;
				break;
			case KeyUp:
				if (event.getType() == KeyPressed) {
					goingForward = true;
				} else if (event.getType() == KeyReleased) {
					goingForward = false;
				}
				keyPressed = false;
				break;
			case KeyLeft:
				if (event.getType() == KeyPressed) {
					turningLeft = true;
				} else if (event.getType() == KeyReleased) {
					turningLeft = false;
				}
				keyPressed = false;
				break;
			case KeyRight:
				if (event.getType() == KeyPressed) {
					turningRight = true;
				} else if (event.getType() == KeyReleased) {
					turningRight = false;
				}
				keyPressed = false;
				break;
			case Space:
				if ((event.getType() == KeyPressed) && (keyPressed == false)) {
					shooting = true;
					keyPressed = true;
				} else if ((keyPressed == true)
						&& (event.getType() == KeyReleased)) {
					keyPressed = false;
					shooting = false;
				}
				break;
			default:
				break;
			}
		}

	}
}

void Ship::resolve() {

	if (turningLeft) {

		float frequency = 1 / this->rotationVelocity;
		float angularRate = fmod(frequency, FRAMES_PER_SECOND)
				/ FRAMES_PER_SECOND;
		if ((angle + (360.0 * angularRate)) <= 359.0) {
			if (360.0 * angularRate >= 1) {
				angle += 360.0 * angularRate;
			} else
				angle++;
		} else if(360.0 * angularRate >= 1)
			angle = angle + (360.0 * angularRate) - 359.0;

	} else if (turningRight) {
		float frequency = 1 / this->rotationVelocity;
		float angularRate = fmod(frequency, FRAMES_PER_SECOND)
				/ FRAMES_PER_SECOND;
		if ((angle - (360.0 * angularRate)) >= 0.0) {
			if (360.0 * angularRate >= 1) {
				angle -= 360.0 * angularRate;
			} else
				angle--;
		} else if(360.0 * angularRate >= 1)
			angle = angle - (360.0 * angularRate) + 359.0;

	}
	int velX = 0;
	int velY = 0;

	if (goingForward) {
		combustion = !combustion;

		float angleInRadians = angle * (M_PI / 180.0);
		velX = velocity * cos(angleInRadians);
		velY = (-1.0) * velocity * sin(angleInRadians);

		if(frictionTimer.is_started()){
			frictionTimer.stop();
		}
		if(!propulsionTimer.is_started()){
			propulsionTimer.start();
		}

			float secs = (propulsionTimer.get_ticks() / 1000.0);
			int acelX = propulsion * cos(angleInRadians) * secs;
			int acelY = (-1.0) * propulsion * sin(angleInRadians) * secs;

			velX += acelX;
			velY += acelY;

			velocity = velocity + propulsion * secs;

			if(velocity > maximumVelocity){
				velocity = maximumVelocity;
				velX = velocity * cos(angleInRadians);
				velY = (-1.0) * velocity * sin(angleInRadians);
			}
			angle0 = angle;
	} else {

		if(combustion)
			combustion = false;

		float angleInRadians = angle0 * (M_PI / 180.0);
		velX = velocity * cos(angleInRadians);
		velY = (-1.0) * velocity * sin(angleInRadians);

		if (propulsionTimer.is_started())
			propulsionTimer.stop();

		if (!frictionTimer.is_started()){
			frictionTimer.start();
		}

		if (velocity > 0) {

			float secs = frictionTimer.get_ticks() / 1000.0;
			float acelX = friction * cos(angleInRadians) * secs;
			float acelY = (-1.0) * friction * sin(angleInRadians) * secs;

			velX -= acelX;
			velY -= acelY;

			velocity = velocity - friction * secs;

			if(velocity < 0){
				velocity = 0;
				velX = 0;
				velY = 0;
			}
		}
	}
	parcel.posX = (int) (parcel.posX + velX);
	parcel.posY = (int) (parcel.posY + velY);

	if(combustion){
		surface = combustionShipSurface;
	}
	else
		surface = shipSurface;
}

int Ship::getBulletAngle() {
	return angle;
}

bool Ship::isShooting() {
	bool result = this->shooting;
	this->shooting = false;
	return result;
}

int Ship::getBulletDuration() const
{
    return bulletDuration;
}


Ship::~Ship() {
}

int Ship::getbulletX() {
	return parcel.posX  + (parcel.height/2)*cos((angle) * M_PI / 180);
}

int Ship::getbulletY() {
	return  parcel.posY - (parcel.height/2)*sin((angle) * M_PI / 180);
}

std::string Ship::getOwner() {
	return owner;
}

ShipStatus Ship::getShipStatus() {
	Parcel parcelAux;
	parcelAux = getPosition();

	return ShipStatus(owner, imagePath, rotationVelocity, maximumVelocity,
			propulsion, friction, bulletDuration, parcelAux.posX,
			parcelAux.posY);
}
